package gf

import (
	"fmt"
	"os"
	"path/filepath"
)

// IsFile 判断指定的文件状态是否为文件。
// 该方法通过文件名获取文件信息，并更新 FileStatus 结构体的属性，
// 以指示文件是否为目录或普通文件，同时记录可能的错误。
func (fi *FileStatus) IsFile() {
	// 初始化 IsDirs 和 IsFiles 为 false，表示尚未确定文件类型
	fi.IsDirs = false
	fi.IsFiles = false
	// 获取文件状态
	fi.stat, fi.Err = os.Stat(fi.FileName)
	// 如果获取文件状态时发生错误，直接返回
	if fi.Err != nil {
		return
	}
	// 判断文件状态是否为目录
	if fi.stat.IsDir() {
		// 如果是目录，设置错误信息，并将 IsDirs 设置为 true
		fi.Err = fmt.Errorf("这是一个文件夹: %s", fi.FileName)
		fi.IsDirs = true
		return
	}
	// 如果不是目录，则将 IsFiles 设置为 true，表示这是一个文件
	fi.Err = nil
	fi.IsFiles = true
}

// IsDir 检查文件状态并设置 IsDirs 字段以指示文件是否为目录。
// 此方法主要用于确定 FileStatus 实例所引用的文件或目录是否为目录。
func (fi *FileStatus) IsDir() {
	// 初始化 IsDirs 字段为 false，假设文件不是目录。
	// 这样做是为了在确定文件实际状态之前提供一个默认值。
	fi.IsDirs = false

	// 获取文件或目录的详细信息，以便后续判断其是否为目录。
	// os.Stat 函数返回文件的信息（如权限、大小、修改时间等）和错误（如果有的话）。
	fi.stat, fi.Err = os.Stat(fi.FileName)

	// 如果在获取文件信息时遇到任何错误，直接返回。
	// 这样做是为了避免在错误未被处理的情况下继续执行后续代码。
	if fi.Err != nil {
		return
	}

	// 根据文件信息判断文件是否为目录，并将结果存储在 IsDirs 字段中。
	// 这是整个方法的核心逻辑，通过文件信息的 IsDir 方法来确定文件类型。
	fi.IsDirs = fi.stat.IsDir()
}

// Exists 检查文件是否存在于文件系统中。
// 该方法通过调用 os.Stat 来获取文件信息，如果文件存在，则更新 ExIst 标志为 true。
// 如果文件不存在或出现其他错误，ExIst 标志保持为 false，并且错误信息会被存储在 Err 属性中。
func (fi *FileStatus) Exists() {
	// 初始化文件存在状态为 false
	fi.ExIst = false
	// 如果没有错误，表示文件存在，将 ExIst 标志设置为 true
	if Exists(fi.FileName) {
		fi.ExIst = true
	}
}

// IsFile 判断给定路径是否指向一个文件。
// 如果路径不存在或指向的是一个目录，则返回false。
// 参数:
//
//	p: 待检查的路径。
//
// 返回值:
//
//	bool: 如果路径指向的是一个文件，则返回true；否则返回false。
func IsFile(p string) bool {
	// 检查路径是否存在。
	if !Exists(p) {
		return false
	}

	// 获取路径对应的信息。
	info, err := os.Stat(p)
	// 如果获取信息时发生错误，则认为路径不指向文件。
	if err != nil {
		return false
	}

	// 检查路径是否指向一个目录。
	if info.IsDir() {
		return false
	}

	// 路径存在且不指向目录，因此认为它指向一个文件。
	return true
}

// IsDir 检查给定路径是否为目录。
// 参数:
//
//	p: 需要检查的路径。
//
// 返回值:
//
//	如果路径存在且为目录，则返回true；否则返回false。
func IsDir(p string) bool {
	// 打开路径
	info, err := os.Stat(p)
	if err != nil {
		logs.Error(err.Error())
		return false
	}
	// 如果路径存在，则返回true；如果路径不存在，则返回false。
	return info.IsDir()
}

// Exists 检查指定路径的文件或目录是否存在。
// 参数:
//
//	p: 需要检查的文件或目录的路径。
//
// 返回值:
//
//	bool: 如果文件或目录存在，则返回true；否则返回false。
//
// 该函数通过调用os.Stat来获取路径的信息，如果路径不存在，则os.Stat会返回错误，从而判断路径是否存在。
func Exists(p string) bool {
	_, err := os.Stat(p)
	return err == nil
}

// GetSubFIle 获取指定目录下的所有文件路径
// 参数:
//
//	dir: 需要遍历的目录路径
//
// 返回值:
//
//	[]string: 文件路径列表
//	error: 如果发生错误，则返回错误信息
func GetSubFIle(dir string) ([]string, error) {
	// 初始化文件列表和目录列表
	var FileList, DirList []string

	// 检查目录是否存在
	if !IsDir(dir) {
		// 如果目录不存在，返回错误信息
		return nil, fmt.Errorf("目标路径不存在: %s", dir)
	}

	// 调用 filepath.Walk 函数来遍历文件夹
	err := filepath.Walk(dir, func(path string, info os.FileInfo, err error) error {
		// 忽略文件夹本身，只处理文件
		if info.IsDir() {
			// 输出文件的路径
			DirList = append(DirList, path)
		} else {
			// 将文件路径添加到文件列表中
			FileList = append(FileList, path)
		}
		return nil
	})

	if err != nil {
		// 如果遍历过程中发生错误，记录错误信息
		fmt.Println("遍历文件夹出错:", err.Error())
		return nil, err
	}
	// 返回文件列表
	return FileList, nil
}
